<?php

namespace App\Models;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;

/**
 * @property int $id
 * @property int $user_id
 * @property int $unit_id
 * @property int $question_count
 * @property int $pre_score
 * @property int $test_score
 * @property int $test_time
 * @property int $is_all_right
 * @property array $questions
 * @property Carbon $submit_at
 * @property Carbon $created_at
 * @property Carbon $updated_at
 * @property User $user
 * @property Collection $answer
 */
class Test extends Model
{
    /**
     * {@inheritdoc}
     */
    protected $casts = [
        'is_all_right' => 'boolean',
    ];

    /**
     * {@inheritdoc}
     */
    public function __construct(array $attributes = [])
    {
        parent::__construct($attributes);

        /** @var User $user */
        $user = Auth::user();

        if ($user) {
            $this->table = 'tests_' . $user->id % 10;
        } else {
            $this->table = 'tests';
        }
    }

    /**
     * 交卷
     *
     * @return $this
     */
    public function submit()
    {
        // 禁止重复提交
        if ($this->submit_at) {
            return $this;
        }

        $answers = static::getAnswersFromCache($this->user_id, $this->id);

        // 回答正确的题目数量
        $rightCount = $answers->where('is_right', true)->count();

        // 提交考试成绩
        $this->test_score = $this->pre_score * $rightCount;
        $this->is_all_right = $this->question_count == $rightCount;
        $this->submit_at = now();

        $this->save();

        // 提交答案选项
        Answer::query()->insertOrIgnore($answers->map(function ($item) {
            if (is_array($item)) {
                $item['answer'] = implode(',', $item['answer']);
            }

            return $item;
        })->toArray());

        // 今日已答题次数
        $qaCount = self::newQuery()
            ->where('user_id', $this->user_id)
            ->where('submit_at', '>', Carbon::today())
            ->count();

        // 获得能量（每天前 10 次，自测每答对 1 题，得 1 能量）
        $score = 0;
        if ($qaCount <= 10) {
            // 用户每天最多获取 200 分，根据注册日期计算最多获取的分值，超过不加分
            if ($this->user->score < ($this->user->created_at->diffInDays() + 1) * 200) {
                $score = $rightCount;
                User::query()->where('id', $this->user_id)->increment('score', $score);
            }
        }

        // 能量值日志
        ScoreLogs::$userId = $this->user_id;
        ScoreLogs::query()->insertOrIgnore([
            'room_id' => 'user_' . $this->user_id . '_test_' . $this->id,
            'user_id' => $this->user_id,
            'pk_user_id' => 0,
            'is_robot' => 2,
            'is_win' => 3, // 是否胜利 0 失败 1 胜利 2 平局 3 自测
            'score' => $score,
            'created_at' => now(),
        ]);

        // 更新当前考试缓存
        Cache::forget('test_for_user_' . $this->user_id);

        return $this;
    }

    /**
     * 从缓存中获取考试的回答
     *
     * @param int $userId
     * @param int $testId
     * @return Collection
     */
    public static function getAnswersFromCache($userId, $testId)
    {
        $answers = Cache::get('answer_for_user_' . $userId . '_test_' . $testId, collect());

        if ($answers->isEmpty()) {
            $answers = Answer::query()
                ->where('user_id', $userId)
                ->where('test_id', $testId)
                ->get()
                ->keyBy('question_id');
        }

        return $answers;
    }

    /**
     * 获取考题
     *
     * @param string $value
     * @return string[]
     */
    public function getQuestionsAttribute($value)
    {
        return explode(',', $value);
    }

    /**
     * 考生答案
     *
     * @return \Illuminate\Database\Eloquent\Relations\hasMany
     */
    public function answer()
    {
        return $this->hasMany(Answer::class);
    }

    /**
     * 考生
     *
     * @return \Illuminate\Database\Eloquent\Relations\belongsTo
     */
    public function user()
    {
        return $this->belongsTo(User::class);
    }

    /**
     * 单位
     *
     * @return \Illuminate\Database\Eloquent\Relations\belongsTo
     */
    public function unit()
    {
        return $this->belongsTo(Unit::class);
    }
}
